package Problem

import (
	"context"

	"github.com/gogf/gf/v2/errors/gcode"
	"github.com/gogf/gf/v2/errors/gerror"

	"Yoj/api/Problem/Create"

	"Yoj/internal/dao"
	"Yoj/internal/model/do"
	"encoding/json"
	"fmt"
	"github.com/gogf/gf/v2/os/glog"
	"strconv"
)

func CheckTitle(ctx context.Context, req *Create.ProblemCreateReq) error {
	exist, err := dao.Problem.Ctx(ctx).Where("title = ?", req.Title).Exist()
	if err != nil {
		glog.Error(ctx, err)
		return gerror.NewCode(gcode.CodeInternalError, "查询数据出错")
	}
	if exist {
		return gerror.NewCode(gcode.CodeInvalidParameter, "标题已经存在")
	}
	return nil
}

func GetJson(ctx context.Context, req *Create.ProblemCreateReq) (input string, output string, limit string, tag string, err error) {
	// input
	inputJson, err := json.Marshal(req.Input)
	if err != nil {
		glog.Error(ctx, err)
		err = gerror.NewCode(gcode.CodeInternalError, "生成json出错")
		return
	}

	// output
	outputJson, err := json.Marshal(req.Output)
	if err != nil {
		glog.Error(ctx, err)
		err = gerror.NewCode(gcode.CodeInternalError, "生成json出错")
		return
	}

	// limit
	limitJson, err := json.Marshal(req.Limit)
	if err != nil {
		glog.Error(ctx, err)
		err = gerror.NewCode(gcode.CodeInternalError, "生成json出错")
		return
	}

	// tag
	type Tag struct {
		Tag []string `json:"tag"`
	}
	tagJson, err := json.Marshal(Tag{Tag: req.Tag})
	if err != nil {
		glog.Error(ctx, err)
		err = gerror.NewCode(gcode.CodeInternalError, "生成json出错")
		return
	}

	return string(inputJson), string(outputJson), string(limitJson), string(tagJson), nil
}

func InsertProblem(ctx context.Context, req *Create.ProblemCreateReq) (res string, err error) {
	// get json
	inputJson, outputJson, limitJson, tagJson, err := GetJson(ctx, req)
	if err != nil {
		glog.Error(ctx, err)
		return
	}

	pid, err := dao.Problem.Ctx(ctx).Data(do.Problem{
		Title:   req.Title,
		Rank:    req.Rank,
		Tag:     tagJson,
		Dc:      req.Dc,
		Input:   inputJson,
		Output:  outputJson,
		Exdc:    req.ExDc,
		Limit:   limitJson,
		Contest: req.Contest,
	}).InsertAndGetId()

	if err != nil {
		glog.Error(ctx, err)
		err = gerror.NewCode(gcode.CodeInternalError, "插入数据出错")
		return
	}
	return strconv.FormatInt(pid, 10), nil
}

func (c *ControllerCreate) ProblemCreate(ctx context.Context, req *Create.ProblemCreateReq) (res *Create.ProblemCreateRes, err error) {
	// print request
	glog.Print(ctx, fmt.Sprintf("req: %v", req))

	// 检查名称;
	if err = CheckTitle(ctx, req); err != nil {
		return nil, err
	}

	// insert
	pid, err := InsertProblem(ctx, req)

	if err != nil {
		return nil, err
	}
	res = &Create.ProblemCreateRes{
		Pid: pid,
	}
	return
}
